package Huella;
import java.awt.Color;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import com.griaule.grFinger.Context;
import com.griaule.grFinger.FingerCallBack;
import com.griaule.grFinger.FingerprintImage;
import com.griaule.grFinger.FingerprintTemplate;
import com.griaule.grFinger.GrErrorException;
import com.griaule.grFinger.GrFinger;
import com.griaule.grFinger.ImageCallBack;
import com.griaule.grFinger.MatchParameters;
import com.griaule.grFinger.MatchingResult;
import com.griaule.grFinger.StatusCallBack;
import com.griaule.grFinger.Version;
import java.awt.Image;
import java.awt.Toolkit;
import java.sql.Statement;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.logging.Level;
import java.util.logging.Logger;


public class Util implements StatusCallBack,ImageCallBack,FingerCallBack{

	private GrFinger grFinger;
	private FormMain ui;
	private boolean autoIdentify = false;
	private boolean autoExtract = true;
	private FingerprintImage fingerprint; 
	private FingerprintTemplate template; 
	private Connection dbConnection;
	private PreparedStatement enrollStmt;
	private PreparedStatement identifyStmt;
	private PreparedStatement clearDbStmt;
	private PreparedStatement verifyStmt;
	private PreparedStatement insertedIdStmt;
    private PreparedStatement entrada;
    private boolean existe = false;
    public int identidad = 1;

	public Util() {
		ui = new FormMain(this);
		ui.setVisible(true);

		try {
			grFinger = new GrFinger();
			Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

			dbConnection = DriverManager.getConnection("jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=Huellas.mdb");

			enrollStmt = dbConnection.prepareStatement("INSERT INTO enroll(template) values(?)");
			identifyStmt = dbConnection.prepareStatement("SELECT * FROM enroll");
			clearDbStmt = dbConnection.prepareStatement("DELETE FROM enroll");
			verifyStmt = dbConnection.prepareStatement("SELECT template FROM enroll WHERE ID=?");
			insertedIdStmt = dbConnection.prepareStatement("SELECT MAX(ID) FROM enroll");
            entrada = dbConnection.prepareStatement("INSERT INTO checadas (ID,Fecha) values (?)");

		} catch (GrErrorException e) {
			ui.writeLog(e.getMessage());
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}


	}

	public static void main(String[] args)  {
		Util sample = new Util();
		sample.start();
	}


	private void start()  {
		try {
			grFinger.initializeCapture(this);
		} catch (GrErrorException e) {
			ui.writeLog(e.getMessage());
		}

	}

	public void onPlug(String idSensor) {
		try {
			grFinger.startCapture(idSensor,this,this);
		} catch (GrErrorException e) {
			ui.writeLog(e.getMessage());
		}

	}

	public void onUnplug(String idSensor) {
		try {
			grFinger.stopCapture(idSensor);
		} catch (GrErrorException e) {
			ui.writeLog(e.getMessage());
		}

	}

	public void onImage(String idSensor, FingerprintImage fingerprint) {
		try {
			ui.showImage(fingerprint.newImageProducer());
            } catch (GrErrorException e) {
			ui.writeLog(e.getMessage());
		}
		ui.jPanel2.setEnabled(true);
        this.fingerprint=fingerprint;
		ui.enableImage();
        ui.jTextArea.setText("");
		extract();
        existe = false;		
		identify();
	}

	public void onFingerDown(String idSensor) {
//		ui.writeLog("Sensor: "+idSensor+". Event: Finger Placed.");
	}


	public void onFingerUp(String idSensor) {
//		ui.writeLog("Sensor: "+idSensor+". Event: Finger Removed.");
	}


	public void enroll() {
		try {
			enrollStmt.setBinaryStream(1,new ByteArrayInputStream(template.getData()),template.getSize());
			enrollStmt.executeUpdate();
			ResultSet rs = insertedIdStmt.executeQuery();
			rs.next();
			ui.writeLog("Huella dada de alta con el ID = "+Integer.toString(rs.getInt(1)));

		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

    public void borrar() {
    ui.jTextArea.setText("");
    ui.image = Toolkit.getDefaultToolkit().getImage("1.png");
    ui.jPanel2.getGraphics().drawImage(ui.image,0,0,ui.jPanel2.getWidth(),ui.jPanel2.getHeight(),null);
       
    }

    public void alta() {
        try {
            String dia;
            String mes;
            String anio;
            String fech;
            String hora;
            String min;
            String sec;
            String clock;
            Calendar c = new GregorianCalendar();
            dia = Integer.toString(c.get(Calendar.DATE));
            mes = Integer.toString(c.get(Calendar.MONTH) + 1);
            anio = Integer.toString(c.get(Calendar.YEAR));
            fech = dia + "/" + mes + "/" + anio;
            hora = Integer.toString(c.get(Calendar.HOUR));
            min = Integer.toString(c.get(Calendar.MINUTE));
            sec = Integer.toString(c.get(Calendar.SECOND));
            clock = hora + ":" + min + ":" + sec;
            String SQLCommand = "INSERT INTO checadas" + "(ID,Fecha,Hora) " + "VALUES " + "( '" + identidad + "','" + fech + "','" + clock + "');";
            Statement stmt = dbConnection.createStatement();
            stmt.execute(SQLCommand);
//	   		entrada.setInt(1, identidad);
//            entrada.executeUpdate();
//            entrada.setString(2, fech);
//            entrada.executeUpdate();
//			ResultSet rs = entrada.executeQuery();
//			rs.next();
            ui.writeLog("Checada Realizada");
        } catch (SQLException ex) {
            Logger.getLogger(Util.class.getName()).log(Level.SEVERE, null, ex);
        }
	}

	public void verify(int id) {
		try {
			verifyStmt.setInt(1,id);
			ResultSet rs = verifyStmt.executeQuery();
			if (rs.next()){
				byte buffer[] = new byte[GrFinger.GR_MAX_SIZE_TEMPLATE];
				InputStream stream = rs.getBinaryStream("template");
				int size = stream.read(buffer);
				FingerprintTemplate referenceTamplate = new FingerprintTemplate(buffer,size);
				MatchingResult result = grFinger.verify(template,referenceTamplate,Context.DEFAULT_CONTEXT);
				if (result.doesMatched()){
					ui.writeLog("Coincidio con un resultado = " + result.getScore() + ".");
					ui.showImage(grFinger.getBiometricDisplay(template,fingerprint,Context.DEFAULT_CONTEXT));
                    return;
				} else
					ui.writeLog("No coincidio con un resultado = " + result.getScore() + ".");
			} else
				ui.writeLog("El ID no existe");
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (GrErrorException e) {
			ui.writeLog(e.getMessage());
		}
	}


	public void identify() {
		byte buffer[] = new byte[GrFinger.GR_MAX_SIZE_TEMPLATE];
		try {
			grFinger.identifyPrepare(template,Context.DEFAULT_CONTEXT);
			ResultSet rs = identifyStmt.executeQuery();
			while (rs.next()){
				InputStream stream = rs.getBinaryStream("template");
				int size = stream.read(buffer);
				FingerprintTemplate referenceTamplate = new FingerprintTemplate(buffer,size);
				MatchingResult result = grFinger.identify(referenceTamplate,Context.DEFAULT_CONTEXT);
				if (result.doesMatched()){
					if (result.getScore() > 60 ){
                        existe = true;
                        identidad = rs.getInt("ID");
						ui.writeLog("Nombre = "+rs.getString("Nombre"));
   				        ui.writeLog("Apellido = "+rs.getString("Apellido"));
//						ui.writeLog("Fingerprint identified. ID = "+rs.getInt("ID")+". Score = " + result.getScore() + ".");
//						ui.showImage(grFinger.getBiometricDisplay(template,fingerprint,Context.DEFAULT_CONTEXT));
					}
                    else
                        ui.writeLog("La huella no pudo ser validada, el score debe ser mayor a 60.");
				return;
				}
			}
			ui.writeLog("Huella no encontrada.");
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (GrErrorException e) {
			ui.writeLog(e.getMessage());
		} catch (IOException e) {
			e.printStackTrace();
		}

	}


	public void extract() {

		try {
			template = grFinger.extract(fingerprint,Context.DEFAULT_CONTEXT);
			String msg = "Template extracted successfully. ";
			switch (template.getImageQuality()){
				case FingerprintTemplate.GR_HIGH_QUALITY:
					msg +="High quality.";
					break;
				case FingerprintTemplate.GR_MEDIUM_QUALITY:
					msg +="Medium quality.";
				    break;
				case FingerprintTemplate.GR_BAD_QUALITY:
					msg +="Bad quality.";
			    	break;
			}
//			ui.writeLog(msg);
			ui.enableTemplate();
			ui.showImage(grFinger.getBiometricDisplay(template,fingerprint,Context.GR_NO_CONTEXT));
		} catch (GrErrorException e) {
			ui.writeLog(e.getMessage());
		}

	}


	public void clearDB() {
		try {
			clearDbStmt.executeUpdate();
			ui.writeLog("Database is clear...");
		} catch (SQLException e) {
			e.printStackTrace();
		}

	}


	public void setAutoIdentify(boolean state) {
		autoIdentify = state;

	}


	public void setAutoExtract(boolean state) {
		autoExtract = state;

	}


	public void stop() {
		try {
			enrollStmt.close();
			clearDbStmt.close();
			identifyStmt.close();
			verifyStmt.close();
			insertedIdStmt.close();
			dbConnection.close();
			grFinger.finalizeCapture();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (GrErrorException e) {
			ui.writeLog(e.getMessage());
		}

	}


	public void setParemeters(int identifyThreshold, int identifyRotationTolerance, int verifyThreshold, int verifyRotationTolorance) {
		try {
			if (grFinger.setIdentifyParameters(new MatchParameters(identifyThreshold,identifyRotationTolerance),Context.DEFAULT_CONTEXT)==GrFinger.GR_DEFAULT_USED)
				ui.writeLog("Invalid identify parameters. Default values used.");
			if (grFinger.setVerifyParameters(new MatchParameters(verifyThreshold,verifyRotationTolorance),Context.DEFAULT_CONTEXT)==GrFinger.GR_DEFAULT_USED)
				ui.writeLog("Invalid verify parameters. Default values used.");
		} catch (GrErrorException e) {
			ui.writeLog(e.getMessage());
		}


	}


	public MatchParameters getVerifyParameters() {
		try {
			return grFinger.getVerifyParameters(Context.DEFAULT_CONTEXT);
		} catch (GrErrorException e) {
			ui.writeLog(e.getMessage());
		}
		return new MatchParameters(0,0);
	}


	public MatchParameters getIdentifyParameters() {
		try {
			return grFinger.getIdentifyParameters(Context.DEFAULT_CONTEXT);
		} catch (GrErrorException e) {
			ui.writeLog(e.getMessage());
		}
		return new MatchParameters(0,0);
	}

	public void setBiometricDisplayColors(Color minutiaeColor, Color minutiaeMatchColor,
			Color segmentColor, Color segmentMatchColor,
			Color directionColor, Color directionMatchColor) {

		try {
			grFinger.setBiometricDisplayColors(minutiaeColor,minutiaeMatchColor,segmentColor,
					segmentMatchColor,directionColor,directionMatchColor);
		} catch (GrErrorException e) {
			ui.writeLog(e.getMessage());
		}

	}

}
